// NewsExtraInfoParser.java

import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;

import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

/**
 * 新闻扩展信息解析类
 */
public class NewsExtraInfoParser {

    /**
     * 获取新闻的来源信息
     *
     * @param document 新闻网页内容
     * @return 新闻来源
     */
    public static String getSource(Document document) {
        // 百家号文章的来源一般在 <p class="index-module_authorName_xxxxx">作者姓名</p> 中可以找到
        if (!document.select("p").isEmpty()) {
            for (Element element : document.select("p")) {
                // 寻找带有 class="index-module_authorName_xxxxx" 属性的 <p> 标签
                if (element.attr("class").contains("authorName")) {
                    // <p> 标签的内容（.text()）即为新闻来源
                    return element.text();
                }
            }
        }
        // 如果上面的流程未找到，则尝试用正则表达式解析
        try {
            // 建立用于匹配来源信息的正则表达式对象，然后进行匹配
            String sourceInfoPatternString = "来源 *([：:])? *\\w+";
            Pattern sourceInfoPattern = Pattern.compile(sourceInfoPatternString);
            Matcher sourceInfoMatcher = sourceInfoPattern.matcher(document.text());
            // 如果匹配成功了，则继续进行处理
            if (sourceInfoMatcher.find()) {
                String sourceInfo = sourceInfoMatcher.group();
                // 建立用于匹配 "来源" 字样的正则表达式对象，然后去掉（替换为空字符串）
                String sourceHeaderPatternString = "来源 *([：:])? *";
                Pattern sourceHeaderPattern = Pattern.compile(sourceHeaderPatternString);
                Matcher sourceHeaderMatcher = sourceHeaderPattern.matcher(sourceInfo);
                return sourceHeaderMatcher.replaceFirst("");
            }
        } catch (PatternSyntaxException e) {
            e.printStackTrace();
        }
        // 如果仍未匹配到，则返回 null
        return null;
    }

    /**
     * 获取新闻的发布时间
     *
     * @param news     新闻基本信息（{@link NewsInfoGetter.News}）
     * @param document 新闻网页内容
     * @return 新闻发布时间 - 如果年份未知，默认与新闻采集时间的年份相同；如果时间未知，则默认是 00:00:00
     */
    public static Timestamp getReleaseTime(NewsInfoGetter.News news, Document document) {
        // 百家号文章的发布时间一般在 <meta itemprop=dateUpdate content="yyyy-MM-dd HH:mm:ss"> 中可以找到
        if (!document.select("meta").isEmpty()) {
            for (Element element : document.select("meta")) {
                // 寻找带有 itemprop=dateUpdate 属性的 <meta> 块
                if (element.attr("itemprop").contains("dateUpdate")) {
                    // content 属性即为新闻发布时间
                    return Timestamp.valueOf(element.attr("content"));
                }
            }
        }
        // 如果上面的流程未找到，则尝试用正则表达式解析

        try {
            // 建立用于匹配日期的正则表达式对象，然后进行匹配
            String datePatternString = "(\\d{4}([-年.]))?[0-1]?\\d([-月.])[0-3]?\\d日?";
            Pattern datePattern = Pattern.compile(datePatternString);
            Matcher dateMatcher = datePattern.matcher(document.text());
            // 如果日期匹配成功了，则继续进行处理
            if (dateMatcher.find()) {
                String date = dateMatcher.group();
                // 把 "yyyy年mm月dd日"、"yyyy.mm.dd" 都转成 "yyyy-mm-dd"的形式
                date = date.replace("年", "-")
                        .replace("月", "-")
                        .replace("日", "")
                        .replace(".", "-");
                // 如果没有年份 "yyyy-"，则添加上新闻采集时间的年份
                if (!Pattern.compile("\\d{4}-").matcher(date).find()) {
                    date = new SimpleDateFormat("yyyy").format(new Date(news.getCollect_time().getTime())) + "-" + date;
                }
                // 建立用于匹配时间的正则表达式对象，然后进行匹配
                String timePatternString = "\\d{1,2}([:：])\\d{1,2}";
                Pattern timePattern = Pattern.compile(timePatternString);
                Matcher timeMatcher = timePattern.matcher(document.text());
                String time;
                if (timeMatcher.find()) {    // 如果匹配到时间则取出
                    time = timeMatcher.group();
                } else {    // 如果没有时间，则添加上 00:00
                    time = "00:00";
                }
                // 把全角时间分隔符改为半角
                time = time.replace("：", ":");
                // 默认秒数是 00
                time = time + ":00";
                if (isValidDatetime(date + " " + time)) {
                    try {
                        // 返回处理后的日期与时间
                        return Timestamp.valueOf(date + " " + time);
                    } catch (IllegalArgumentException e) {
                        System.out.println(date + " " + time + "，时间处理错误，链接为：" + news.getHref() + "\n网页信息（仅文字）为：\n" + document.text());
                        e.printStackTrace();
                    }
                }
            }
        } catch (PatternSyntaxException e) {
            e.printStackTrace();
        }
        // 如果仍未匹配到，则返回 null
        return null;
    }

    public static boolean isValidDatetime(String datetime) {
        boolean convertSuccess = true;
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        format.setLenient(false);
        try {
            format.parse(datetime);
        } catch (ParseException e) {
            convertSuccess = false;
        }
        return convertSuccess;
    }
}
